package my.dao.daoImpl;

import my.dao.CommonDao;
import my.utils.ObjUtils;
import my.vo.voImpl.Book;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author 星环
 * @date 2022/11/13 11:39:18
 * @description
 */
public class BookDao extends CommonDao<Book> {

    private static final BookDao bookDao = new BookDao();

    private BookDao() {
        super(new Book());
    }

    /**
     * 单例，返回自己的唯一实例
     * @return 存储的实例
     */
    public static BookDao getInstance(){
        return bookDao;
    }


    /**
     * 按id删除
     * @param id 要删除的书的id
     * @return 如果删掉了，书，否则null
     */
    public Book deleteById(int id){
        List<Book> books = deleteBy(book -> book.getId() == id);
        return (Book) ObjUtils.getFirstOrNull(books);
    }

    /**
     * 按名字删除，话说这些重复了三遍，我不会要写三遍注释吧
     * 因为可能重名，返回被删掉的书的列表
     * @param name 书名
     * @return 被删掉书的列表，如果没有，size就是0
     */
    public List<Book> deleteByName(String name){
        return deleteBy(book -> book.getName().equals(name));
    }

    /**
     * 根据id更新书
     *
     * @param book 要更改的信息
     */
    public List<Book> updateById(Book book){
        List<Book> books = list.stream().filter(book1 -> book1.getId() == book.getId()).toList();
        books.forEach(book1 -> {
            if(book.getName() != null){
                book1.setName(book.getName());
            }
            if(book.getAuthor() != null){
                book1.setAuthor(book.getAuthor());
            }
            if(book.getPublishingHouse() != null){
                book1.setPublishingHouse(book.getPublishingHouse());
            }
            if(book.getTypeId() >= 0){
                book1.setTypeId(book.getTypeId());
            }
            if(book.getBorrowerId() >= 0){
                book1.setBorrowerId(book.getBorrowerId());
            }
        });
        return viewOf(books);
    }

    /**
     * 取得所有书
     * @return 所有书的列表
     */
    public List<Book> getAll(){
        return srchBy(book -> true);
    }

    /**
     * 按名字找书
     * @param name 书名
     * @return 书列表
     */
    public List<Book> getByName(String name){
        return srchBy(book -> book.getName().equals(name));
    }

    /**
     * 按id找书
     * @param id 书的id
     * @return 找得到book，找不到null
     */
    public Book getById(int id){
        List<Book> books = srchBy(book -> book.getId() == id);
        return (Book) ObjUtils.getFirstOrNull(books);
    }

    /**
     * 按类别id找书
     * @param btId 书类id
     * @return 找到的书
     */
    public List<Book> getBooksByTypeId(int btId){
        //lambda挺好用
        return srchBy(book -> book.getTypeId() == btId);
    }

    /**
     * 返回按多个类别找书，但是控制台里，怎么会用到这个方法呢
     * @param ids 类别id列表
     * @return 找到的书
     */
    public List<Book> getBooksByTypeIds(List<Integer> ids){
        //书的类别一定比较少，就用set存，防止遍历，O1
        Set<Integer> idSet = new HashSet<>(ids);
        //如果idSet里有这个类别，就加入list
        List<Book> books = list.stream().filter(e -> idSet.contains(e.getTypeId())).toList();
        return viewOf(books);
    }

    /**
     * 按借阅者id查书，用于读者查找自己的书
     * @param uid 读者的id
     * @return 他借的书
     */
    public List<Book> getBooksByBorrowerId(int uid){
        return srchBy(book -> book.getBorrowerId() == uid);
    }

    /**
     * 把这个人借的书全还了
     * @param uid
     */
    public List<Book> returnAllBookByUserId(int uid){
        return updateBy(book -> book.getBorrowerId() == uid,
                book -> book.setBorrowerId(0));
    }

    /**
     * 删除一类书
     * @param id 类别的id
     * @return 删除书的列表
     */
    public List<Book> deleteByTypeId(int id) {
        return deleteBy(book -> book.getId() == id);
    }

    /**
     * 更新{@code oldId}类别的书为新类{@code id}
     * @param oldId 旧类别id
     * @param id 新的类别id
     * @return 更改的书的列表
     */
    public List<Book> updateTypeId(int oldId, int id) {
        return updateBy(book -> book.getTypeId() == oldId,
                book -> book.setTypeId(id));
    }

    public List<Book> borrowBook(int bookId, int readerId) {
        return updateBy(book -> book.getId() == bookId && book.getBorrowerId() == 0,
                book -> book.setBorrowerId(readerId));
    }

    /**
     * 按id还书，如果id为0，还了所有的书
     * @param id
     * @return
     */
    public List<Book> returnMyBookById(int readerId, int id) {
        return updateBy(book -> book.getBorrowerId() == readerId && book.getId() == id,
                book -> book.setBorrowerId(0));
    }

    public List<Book> updateTypeIdById(int id, int newId) {
        return updateBy(book -> book.getId() == id,
                book -> book.setTypeId(newId));
    }
}
